package internal

import (
	"BJXM_Shooting/db/set"
	"BJXM_Shooting/msg"
	"fmt"
	"github.com/name5566/leaf/gate"
	g "github.com/name5566/leaf/go"
	"github.com/name5566/leaf/log"
	"github.com/name5566/leaf/timer"
	"github.com/name5566/leaf/util"
	"sync"
	"time"
)

var (
	users = RWUsers{data: make(map[string]*User)}
)

type RWUsers struct {
	sync.RWMutex
	data map[string]*User
}

const (
	stateLogin  = iota //已登录
	stateLogout        //登出了
	stateLobby         //在大厅中

	stateMatching //匹配中

	// 进行游戏
	stateReady      //准备完毕
	stateLoadBattle //加载战斗过程中,即开始游戏
	stateGame       //游戏中

)

type User struct {
	gate.Agent
	*g.LinearContext
	state       int
	data        *set.User
	saveDBTimer *timer.Timer
	matching    *msg.C2S_Matching
	auth        bool   //是否登录验证过
	desk        string //桌号 = md5(account1 + account2)
	index       int    //射箭顺序
	score       int    //当前对局的分数
	gameReady   bool   //是否已经进入游戏准备好
}

func (this *User) login(account string) {
	// 添加心跳包计时
	//this.pongTime = time.Now().UnixNano() / 1e6
	userData := &set.User{}
	skeleton.Go(func() {
		// 拿到账号详情信息
		var err error
		userData, err = set.FindUser(account)
		if err != nil {
			log.Error("加载用户数据失败:%s", err.Error())
			userData = nil
			this.WriteMsg(&msg.S2C_Close{
				ID:  msg.S2C_ID_InnerError,
				Msg: fmt.Sprintf("加载用户数据失败:%s", err.Error()),
			})
			this.Close()
			return
		}
	}, func() {
		// 网络错误时
		if this.state == stateLogout {
			this.logout(account)
			return
		}
		// 数据库错误
		this.state = stateLobby
		if userData == nil {
			return
		}
		// 成功
		this.data = userData

		users.Lock()
		users.data[userData.Account] = this
		users.Unlock()

		// 返回账号信息给客户端
		this.WriteMsg(&msg.S2C_User{
			Account:  this.data.Account,
			Nickname: this.data.Nickname,
			Avatar:   this.data.Avatar,
			Level:    this.data.Level,
			Gold:     this.data.Gold,
		})

		this.auth = true
		this.autoSaveDB()
	})
}

// 用户登出
func (this *User) logout(account string) {
	// 检测用户是否还存在
	users.RLock()
	if _, exist := users.data[account]; !exist {
		users.RUnlock()
		log.Release("检测到账户已经不存在:%s", account)
		return
	}
	users.RUnlock()

	log.Release("又触发退出")

	// 让其时钟停止
	// 调用onLogout
	// 删除map中的该账户
	if this.data != nil {
		log.Release("删除对象:%s" , this.data.Nickname)

		this.state = stateLogout
		this.saveDBTimer.Stop()

		// 删除匹配中的,与users中的map
		deleteMatching <- this.data.Account
		users.Lock()
		delete(users.data, this.data.Account)
		users.Unlock()
	}

	// 保存
	data := util.DeepClone(this.data)
	this.Go(func() {
		if data != nil {
			set.UserUpdate(data.(*set.User))
		}
	}, func() {
		// 销毁当前这个goroutine,也会触发rpcCloseAgent()函数
		this.Destroy()
	})
}

// 自动保存用户信息
func (this *User) autoSaveDB() {
	const duration = 1 * time.Second
	// 放到定时器里定时保存
	this.saveDBTimer = skeleton.AfterFunc(duration, func() {
		data := util.DeepClone(this.data)
		var err error
		this.Go(func() {
			err = set.UserUpdate(data.(*set.User))
			if err != nil {
				log.Error("自动保存失败:%v ,Object:%+v", err, data)
			}
		}, func() {
			this.autoSaveDB()
		})
	})
}

// 是否离线
func (this *User) isOffline() bool {
	return this.state == stateLogout
}
